﻿using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using CNF.Common.Base.SimpleOrm.DataBaseProvidrer;
using CNF.Common.Base.SimpleOrm.Entities;
using PetaPoco;

namespace CNF.Common.Base.SimpleOrm.Data
{
    public abstract class BaseViewDataService<DataKeyType, EntityType> : IViewDataService<DataKeyType, EntityType>
        where DataKeyType : struct
        where EntityType : BaseEnity<DataKeyType>, new()
    {

        protected IDataBaseStoreage<Database> dataBaseStoreage;
        protected string dataBaseKey;

        protected BaseViewDataService(IDataBaseStoreage<Database> dataBaseStoreage,string dataBaseKey)
        {
            this.dataBaseStoreage = dataBaseStoreage;
            this.dataBaseKey = dataBaseKey;
        }

        protected Database CurrentDatabase
        {
            get { return dataBaseStoreage.GetCurentDataBaseByKey(dataBaseKey); }
        }

       public ITransaction Transaction 
       {
            get { return CurrentDatabase.GetTransaction(); }
       }
 

        public EntityType LoadByID(DataKeyType dataKey)
        {
            return CurrentDatabase.SingleOrDefault<EntityType>(dataKey);
        }

        protected List<EntityType> QueryListBySQL(string sql, params object[] args)
        {
            return CurrentDatabase.Query<EntityType>(sql, args).ToList();
        }

        protected List<EntityType> QueryListBySQL(Sql sql)
        {
            return CurrentDatabase.Query<EntityType>(sql).ToList();
        }

        public List<EntityType> QueryAll()
        {
            return QueryListByCondition(" where 1=1 ");
        }

 
        protected List<EntityType> QueryListByCondition(string condition, params object[] args)
        {
            return CurrentDatabase.Query<EntityType>(string.Format("Select * from {0} {1}", GetDbObjectName(),condition), args).ToList();
        }


        protected EntityType QuerySingleBySQL(string sql, params object[] args)
        {
            return CurrentDatabase.FirstOrDefault<EntityType>(sql, args);
        }

        protected EntityType QuerySingleBySQL(Sql sql)
        {
            return CurrentDatabase.FirstOrDefault<EntityType>(sql);
        }

        protected EntityType QuerySingleByCondition(string condition, params object[] args)
        {
            return CurrentDatabase.FirstOrDefault<EntityType>(string.Format("Select Top 1 * from {0} {1}", GetDbObjectName(), condition), args);
        }
 
        protected T ExecuteScalar<T>(string sql, params object[] args)
        {
            return CurrentDatabase.ExecuteScalar<T>(sql, args);
        }

        protected T ExecuteScalar<T>(Sql sql)
        {
            return CurrentDatabase.ExecuteScalar<T>(sql);
        }

        protected Page<EntityType> Page(long page, long itemsPerPage, string sql, params object[] args)
        {
            return CurrentDatabase.Page<EntityType>(page, itemsPerPage, sql, args);
        }

        protected Page<EntityType> Page(long page, long itemsPerPage, Sql sql)
        {
            return CurrentDatabase.Page<EntityType>(page, itemsPerPage, sql);
        }

        protected bool Exists(string sqlCondition, params object[] args)
        {
            return CurrentDatabase.Exists<EntityType>(sqlCondition, args);
        }

        public bool Exists(object primaryKey)
        {
            return CurrentDatabase.Exists<EntityType>(primaryKey);
        }
 

        public bool IsNew(EntityType poco)
        {
            return CurrentDatabase.IsNew(poco);
        }

        protected Sql CreateDefaultSelectSql()
        {
            Sql sql = new Sql();

            sql.Select(" * ").From(GetDbObjectName()).Where(" 1=1 ");

            return sql;
        }

        protected Sql CreateDefaultTopSelectSql(int topCount)
        {
            Sql sql = new Sql();

            sql.Select(" TOP " + topCount.ToString() + " * ").From(GetDbObjectName()).Where(" 1=1 ");

            return sql;
        }

        protected string Not(string express)
        {
            return string.Format(" NOT ({0}) ", express);
        }

        protected string And(params string[] express)
        {
            StringBuilder sbAndExpress = new StringBuilder();

            sbAndExpress.Append(" ( ");

            for (int i = 0; i < express.Length; i++)
            {
                sbAndExpress.AppendFormat(" ({0}) ", express[i]);

                if (i < express.Length - 1)
                {
                    sbAndExpress.Append(" AND ");
                }
            }

            sbAndExpress.Append(" ) ");

            return sbAndExpress.ToString();
        }

        protected string Or(params string[] express)
        {
            StringBuilder sbAndExpress = new StringBuilder();

            sbAndExpress.Append(" ( ");

            for (int i = 0; i < express.Length; i++)
            {
                sbAndExpress.AppendFormat(" ({0}) ", express[i]);

                if (i < express.Length - 1)
                {
                    sbAndExpress.Append(" OR ");
                }
            }

            sbAndExpress.Append(" ) ");

            return sbAndExpress.ToString();
        }

        public abstract string GetDbObjectName();

        public abstract string GetPkName();
    }
}
